package com.bodu.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bodu.core.entity.ParamReq;
import com.bodu.core.entity.enums.DelFlagEnum;
import com.bodu.core.exception.custom.SaveException;
import com.bodu.core.exception.custom.UpdateException;
import com.bodu.system.entity.po.MenuPermitPo;
import com.bodu.system.entity.po.PermitPo;
import com.bodu.system.entity.po.RolePermitPo;
import com.bodu.system.entity.request.MenuPermitRequest;
import com.bodu.system.entity.request.PermitRequest;
import com.bodu.system.entity.request.RolePermitRequest;
import com.bodu.system.entity.vo.PermitVo;
import com.bodu.system.mapper.MenuPermitMapper;
import com.bodu.system.mapper.PermitMapper;
import com.bodu.system.mapper.RolePermitMapper;
import com.bodu.system.service.PermitService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * 权限这块存在的问题：
 * 若可以对用户进行赋权的用户没有更加高级的权限，但是在赋权过程中，确可以进行更高级别的权限赋权，所以肯定会存在问题的。
 *
 * @author r.guo
 * @since 2019-05-25
 */
@Service("permitService")
public class PermitServiceImpl implements PermitService {
    /**
     * 最高编号
     */
    private final static Long ROOT_ID = -1L;

    @Resource
    private PermitMapper permitMapper;

    @Resource
    private RolePermitMapper rolePermitMapper;

    @Resource
    private MenuPermitMapper menuPermitMapper;

    @Override
    public PermitVo getModel(Long id) {
        PermitPo permitPo = permitMapper.getModel(id);
        PermitVo permitVo = new PermitVo();
        BeanUtils.copyProperties(permitPo, permitVo);
        return permitVo;
    }

    @Transactional(rollbackFor = SaveException.class)
    @Override
    public Long save(PermitRequest request) {
        permitMapper.save(request);
        return request.getId();
    }

    @Transactional(rollbackFor = UpdateException.class)
    @Override
    public Long update(PermitRequest request) {
        permitMapper.update(request);
        return request.getId();
    }

    @Override
    public List<PermitVo> listPage(ParamReq<PermitRequest> params) {
        return permitMapper.listPage(params);
    }

    @Override
    public Integer countPage(ParamReq<PermitRequest> params) {
        return permitMapper.countPage(params);
    }

    @Override
    public List<PermitVo> loopList() {
        PermitRequest permitRequest = new PermitRequest();
        permitRequest.setDelFlag(DelFlagEnum.NO.getValue());
        ParamReq<PermitRequest> requestParamReq = new ParamReq<>();
        requestParamReq.setEntity(permitRequest);
        Integer total = countPage(requestParamReq);
        requestParamReq.setSize(total);
        // 得到所有的权限
        List<PermitVo> permitLists = listPage(requestParamReq);
        List<PermitVo> rootPermit = CollUtil.newArrayList();
        for (PermitVo p : permitLists) {
            if (p.getParentId().equals(ROOT_ID)) {
                setPermitParentName(p);
                rootPermit.add(loopPermits(p, permitLists));
            }
        }
        return rootPermit;
    }

    @Override
    public List<Long> listPermitIdByRoleId(Long roleId) {
        if (ObjectUtil.isEmpty(roleId)) {
            return CollUtil.newArrayList();
        }
        return permitMapper.listPermitIdByRoleId(roleId);
    }

    @Transactional(rollbackFor = SaveException.class)
    @Override
    public Integer savePermitByRoleId(RolePermitRequest request) {
        Long roleId = request.getRoleId();
        List<Long> permitIds = request.getPermitIds();
        RolePermitPo permitPo = new RolePermitPo();
        permitPo.setRoleId(roleId);
        permitPo.setDelFlag(request.getDelFlag());
        permitPo.setCreateUser(request.getCreateUser());
        permitPo.setPermitIds(CollUtil.newHashSet(permitIds));
        return rolePermitMapper.batchSave(permitPo);
    }

    @Override
    public Integer savePermitByMenuId(MenuPermitRequest request) {
        Long menuId = request.getMenuId();
        List<Long> permitIds = request.getPermitIds();
        if (ObjectUtil.isNotEmpty(permitIds) && permitIds.size() > 0) {
            MenuPermitPo permitPo = new MenuPermitPo();
            permitPo.setMenuId(menuId);
            permitPo.setDelFlag(DelFlagEnum.NO.getValue());
            permitPo.setCreateUser(request.getCreateUser());
            permitPo.setPerimitIds(CollUtil.newHashSet(permitIds));
            return menuPermitMapper.batchSave(permitPo);
        }
        return 0;
    }

    @Override
    public List<Long> listPermitIdByMenuId(Long menuId) {
        if (ObjectUtil.isEmpty(menuId)) {
            return CollUtil.newArrayList();
        }
        return permitMapper.listPermitIdByMenuId(menuId);
    }

    private PermitVo loopPermits(PermitVo rootPermit, List<PermitVo> permitList) {
        setPermitParentName(rootPermit);
        List<PermitVo> chidren = CollUtil.newArrayList();
        for (PermitVo p : permitList) {
            if (p.getParentId().equals(rootPermit.getId())) {
                chidren.add(loopPermits(p, permitList));
            }
        }
        rootPermit.setChildren(chidren);
        return rootPermit;
    }

    /**
     * 设置permit的parent Name 名称
     *
     * @param rootPermit
     */
    private void setPermitParentName(PermitVo rootPermit) {
        if (ObjectUtil.isNotEmpty(rootPermit.getParentId()) && !ObjectUtil.equals(rootPermit.getParentId(), -1L)) {
            PermitPo parentPermit = getModel(rootPermit.getParentId());
            if (ObjectUtil.isNotEmpty(parentPermit)) {
                rootPermit.setParentPermitName(parentPermit.getAuthorityName());
            } else {
                rootPermit.setParentPermitName(" - ");
            }
        } else {
            rootPermit.setParentPermitName(" - ");
        }
    }

    @Override
    public Integer updateDelFlagById(Long id, Integer delFlag) {
        return permitMapper.updateDelFlagById(id, delFlag);
    }

    @Override
    public List<PermitPo> listByAdminId(Long id) {
        return permitMapper.listByAdminId(id);
    }
}
